package com.biwin.module.orm.starter.repository.impl;

import com.biwin.common.app.basic.BwPage;
import com.biwin.common.app.basic.BwQueryDto;
import com.biwin.module.orm.api.entity.BwBasicEntity;
import com.biwin.module.orm.api.repository.IBwBasicRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.support.CustomJpaRepository;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.List;

/**
 * Entity Repository Implementation For JPA Specification
 *
 * @author biwin
 * @since 0.0.1
 */
public class BwBasicRepositoryImpl<T, ID extends Serializable> extends CustomJpaRepository<T, Serializable>
        implements IBwBasicRepository<T, Serializable> {

    private static Logger log = LoggerFactory.getLogger(BwBasicRepositoryImpl.class);
    private final EntityManager entityManager;
    private Class<T> entityClass;

    public BwBasicRepositoryImpl(Class<T> domainClass, EntityManager em) {
        super(domainClass, em);
        this.entityManager = em;
        this.entityClass = domainClass;
    }

    /**
     * 根据 BwQueryObject 执行列表查询
     *
     * @param query
     * @return
     */
    public List<T> queryList(BwQueryDto query) {
        Specification<T> specification = builderQuery(query);
        Sort sort = getOrder(query);
        String[] groupBys = getGroupBys(query);
        List<T> entityList = findAll(specification, groupBys, sort);
        return entityList;
    }

//    @Override
//    public T find(Serializable id) {
//        return entityManager.find(entityClass, id);
//    }

    private String[] getGroupBys(BwQueryDto query) {

        return null;
    }

    private Sort getOrder(BwQueryDto query) {

        return null;
    }

    private Specification<T> builderQuery(BwQueryDto query) {
        return (Specification<T>) ((root, criteriaQuery, criteriaBuilder) -> {

            return null;
        });
    }

    /**
     * 根据 BwQueryObject 执行分页查询
     *
     * @param query
     * @param page
     * @return
     */
    public BwPage queryPage(BwQueryDto query, BwPage page) {

        return null;
    }

    /**
     * 根据 BwQueryObject 执行列表查询,并仅返回 fields 中的字段
     *
     * @param query
     * @param fields
     * @return
     */
    public List<T> queryList(BwQueryDto query, String[] fields) {

        return null;
    }

    /**
     * 根据 BwQueryObject 执行单条记录查询
     * 该方法必须由调用方自行确认返回的数据仅有一条,否则底层将从返回的结果中取第一条记录,或者返回null.
     *
     * @param query
     * @return
     */
    public T queryOne(BwQueryDto query) {

        return null;
    }

    /**
     * 根据 Id 进行记录查询
     *
     * @param id
     * @return
     */
    public T queryById(Long id) {

        return null;
    }

    /**
     * 根据 Id 集合进行记录查询
     *
     * @param id
     * @return
     */
    public List<T> queryByIds(Long... id) {

        return null;
    }

    /**
     * 根据 Id 集合进行记录查询
     *
     * @param ids
     * @return
     */
    public List<T> queryByIds(List<Long> ids) {

        return null;
    }

    /**
     * 根据主键逻辑删除
     *
     * @param serializable
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean falseDelete(Serializable serializable) {
        boolean result = false;
        try {
            T t = (T) getOne( serializable);
            Class clazz = t.getClass();
            if (t instanceof BwBasicEntity) {
                Boolean deleted = ((BwBasicEntity) t).getDeleted();
                if (!deleted) {
                    //强制改变已过期的假删数据
//                    doPhysicsUpdateHistoryData(t);
                    Class superclass = getParentClass(clazz);
                    Method setIsDel = superclass.getDeclaredMethod("setDeleted", Boolean.class);
                    setIsDel.invoke(t, true);
                    super.save(t);
                }
                result = true;
            }
        } catch (Exception e) {
            log.error("falseDelete error", e);
        }
        return result;
    }

    /**
     * 根据 BwQueryObject 返回总记录数
     *
     * @param query
     * @return
     */
//    public long count(BwQueryDto query) {
//
//        return 0L;
//    }


    public boolean deleteBatch(Long... ids) {
        return false;
    }

    public boolean deleteBatch(List<Long> ids) {
        return false;
    }

    private Class getParentClass(Class clazz) {
        Class superclass = clazz.getSuperclass();
        if (superclass != BwBasicEntity.class) {
            return getParentClass(superclass);
        }
        return superclass;
    }

}
